# -*- coding: utf-8 -*-
import requests
import base64
import json
import urllib

# TODO: (clientId, clientSecret, tokenUrl)请使用实际值替换
# App secret, 在AppGallery Connect创建应用之后，系统自动分配的公钥
#  clientSecret ==         "appSecret": "2pi9wffoj9dn633vdb2p85u2oeehmp6o",
clientSecret = "2pi9wffoj9dn633vdb2p85u2oeehmp6o"
# client id指的是您的APP ID
# App ID, 在AppGallery Connect创建应用之后，系统自动分配的唯一标识符
#  clientId ==         "appId": "1003400",
clientId = "1003400"
# 用于获取authorization token的url，具体请参见基于OAuth 2.0开放鉴权
TokenUrl = "https://oauth-login.cloud.huawei.com/oauth2/v3/token"
# accessToken信息
accessToken = None

"""
华为应用 AT 信息 
[
    {
        "channel": "huawei",
        "applicationId": "1003400",
        "huaweiV2PublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArQXTBLKwc69cXNXUGc1dVNFtjJ5rhWcPsZtKYTw6p23lwSNCNxTZhhDzTqkuuD6QsmeZA/OPUCXQOZq+vXrGgNKBTbrdCTAQQdtIJrl2xaP3DikzHErcqYCo3EIhajSknDE9fHb2JUMY2JirH/WdHdtBiHp/PA/savjNSX/i2wZpIw4LoYRiw4IN1XrzD+NjYDimx5Z8eYNH7DtseAed2xbQZmIPuHij2XSPDrdzVw6iBzBPgrBIP9KwqNx+IGl4WM+PYZkIjwxy6mszvS8phfbpybJQnBqHO6F7LN1VLCAGflrMcczVxMyRd9pX+HsMncl/qMRLh/SgPWrUI0MhGwIDAQAB",
        "huaweiIapPayVersion": "2.0",
        "huaweiVersion2CallBackUrl": "http://lcts6.ssjlicai.com/payment-callback-ws/iap/huawei/callback/CN20210425849",
        "merchantId": "2850086000366916932",
        "merchantName": "深圳市铭数信息有限公司",
        "huaweiV3PublicKey": "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA1CJ3mbplMuScjh33yzJP2a1BpWoNmW8s/fxkRukN5ku2IWv7pVDl6yBBmnKzZmcpy0WWQpXVrsqfff51HTwrYViCEVck20uLD8YykxKa9CrTnwRFgsUX0sz3rKhJ1JqArXHB8tKyUG6r/2SpA0RFm0D6Af97HKAgj6g9TviUwCPHBtQ+d8gDjCHoAaURbEg2MEUh5DyVBoVi1gsi5nsJuifFJhyaneSLtS5PV0PKPqnT/LHaarMJXRaV7tIUYDaxT1vF2udLUiVw53iyiyLk44yadwzp/pKql4OCaUOvJNkeSU53mA6542cT42pR+N/fZTB+pDN3/l3hVocrxGik9yel5T3yRWtCVbNUj8ECJD76GDq3IJATyKraGHHiCsQTV5CyV8EJFl1mAL1X/uixf9tIrMctNYsIogkN4ny0/nd/vEnTBc9zKVHRn658QICnr2VhITEzUlckW2MEhBhfUawU0dN5+loEFkpv2e79PpsY1GTCh31ZCUL6w9u7z6BzAgMBAAE=",
        "rootUrl": "https://orders-drcn.iap.hicloud.com",
        "tokenUrl": "https://oauth-login.cloud.huawei.com/oauth2/v3/token",
"subscriptionRootUrl":"https://subscr-drcn.iap.cloud.huawei.com.cn",
        "appId": "1003400",
        "appSecret": "2pi9wffoj9dn633vdb2p85u2oeehmp6o",
        "appProduct": "MyMoney For Huawei"
    },
    {
        "channel": "huawei",
        "applicationId": "10786431",
        "huaweiV2PublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArQXTBLKwc69cXNXUGc1dVNFtjJ5rhWcPsZtKYTw6p23lwSNCNxTZhhDzTqkuuD6QsmeZA/OPUCXQOZq+vXrGgNKBTbrdCTAQQdtIJrl2xaP3DikzHErcqYCo3EIhajSknDE9fHb2JUMY2JirH/WdHdtBiHp/PA/savjNSX/i2wZpIw4LoYRiw4IN1XrzD+NjYDimx5Z8eYNH7DtseAed2xbQZmIPuHij2XSPDrdzVw6iBzBPgrBIP9KwqNx+IGl4WM+PYZkIjwxy6mszvS8phfbpybJQnBqHO6F7LN1VLCAGflrMcczVxMyRd9pX+HsMncl/qMRLh/SgPWrUI0MhGwIDAQAB",
        "huaweiVersion2CallBackUrl": "http://lcts6.ssjlicai.com/payment-callback-ws/iap/huawei/callback/CN20210425849",
        "merchantId": "2850086000366916932",
        "merchantName": "深圳市铭数信息有限公司",
        "huaweiV3PublicKey": "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAhdyplX/XtkfSwNhR+9ueEFjMDByUiFFqO+p2jpTh6g48+waYtfwXdLBqyLqO34rtdHqIJc/1ZQwMazdbtUtGwMLD2T3pvYsVvlnEt34czRNTTv/W3GwOahFr+qnis4yjQgyC2moFSeZQeWWlzXj49azhN8AfPk7EiT/aacl3mWDkF/+qWkPN+h5IdYV9M09H6JoDxeJ8uQ7MOSUY/KFkJZLjKYzyjddYzrQEhbbDiO/tfZ1atEgs0RwEAUQotW6a5qNc03byM7ls+WZcblEguscDD2tgLo4AGdboeujTN2Bz9C2moK1zJ5SO9Yu9FLDqAR9TmncvorRw/L+MJTNJjzopXJk/aG9BMB7jOGKfbdHcPy7EkWfSQ2PUguDD5rTy8F+dcEUIFOgY4tMcpNwKuK3zW884v1Js17fYgE3htST2OQlskrJ5TkOBP3mW8Y6C4AHSAVbTV7vcLcefl7wUlB4qPedljaXjK8xcIgF9QZUqXaW6MRAH8AKFoxPf09mdAgMBAAE=",
        "rootUrl": "https://orders-drcn.iap.hicloud.com",
        "tokenUrl": "https://oauth-login.cloud.huawei.com/oauth2/v3/token",
"subscriptionRootUrl":"https://subscr-drcn.iap.cloud.huawei.com.cn",
        "appSecret": "a8964a707ec233e8d4a83e0ee196dc30",
        "appProduct": "MyMoney For Huaweipro",
        "appId": "10786431"
    },
    {
        "channel": "huawei",
        "applicationId": "1003400",
        "huaweiV2PublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArQXTBLKwc69cXNXUGc1dVNFtjJ5rhWcPsZtKYTw6p23lwSNCNxTZhhDzTqkuuD6QsmeZA/OPUCXQOZq+vXrGgNKBTbrdCTAQQdtIJrl2xaP3DikzHErcqYCo3EIhajSknDE9fHb2JUMY2JirH/WdHdtBiHp/PA/savjNSX/i2wZpIw4LoYRiw4IN1XrzD+NjYDimx5Z8eYNH7DtseAed2xbQZmIPuHij2XSPDrdzVw6iBzBPgrBIP9KwqNx+IGl4WM+PYZkIjwxy6mszvS8phfbpybJQnBqHO6F7LN1VLCAGflrMcczVxMyRd9pX+HsMncl/qMRLh/SgPWrUI0MhGwIDAQAB",
        "huaweiIapPayVersion": "2.0",
        "huaweiVersion2CallBackUrl": "http://lcts6.ssjlicai.com/payment-callback-ws/iap/huawei/callback/CN20210425849",
        "merchantId": "2850086000366916932",
        "merchantName": "深圳市铭数信息有限公司",
        "huaweiV3PublicKey": "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA1CJ3mbplMuScjh33yzJP2a1BpWoNmW8s/fxkRukN5ku2IWv7pVDl6yBBmnKzZmcpy0WWQpXVrsqfff51HTwrYViCEVck20uLD8YykxKa9CrTnwRFgsUX0sz3rKhJ1JqArXHB8tKyUG6r/2SpA0RFm0D6Af97HKAgj6g9TviUwCPHBtQ+d8gDjCHoAaURbEg2MEUh5DyVBoVi1gsi5nsJuifFJhyaneSLtS5PV0PKPqnT/LHaarMJXRaV7tIUYDaxT1vF2udLUiVw53iyiyLk44yadwzp/pKql4OCaUOvJNkeSU53mA6542cT42pR+N/fZTB+pDN3/l3hVocrxGik9yel5T3yRWtCVbNUj8ECJD76GDq3IJATyKraGHHiCsQTV5CyV8EJFl1mAL1X/uixf9tIrMctNYsIogkN4ny0/nd/vEnTBc9zKVHRn658QICnr2VhITEzUlckW2MEhBhfUawU0dN5+loEFkpv2e79PpsY1GTCh31ZCUL6w9u7z6BzAgMBAAE=",
        "rootUrl": "https://orders-drcn.iap.hicloud.com",
        "tokenUrl": "https://oauth-login.cloud.huawei.com/oauth2/v3/token",
"subscriptionRootUrl":"https://subscr-drcn.iap.cloud.huawei.com.cn",
        "appId": "1003400",
        "appSecret": "2pi9wffoj9dn633vdb2p85u2oeehmp6o",
        "appProduct": "general"
    }
]
"""


def getAppAT():
    """获取应用级AccessToken."""
    global accessToken
    if accessToken is not None and accessToken != "":
        return accessToken
    headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
    bodyDict = {"grant_type": "client_credentials", "client_secret": clientSecret, "client_id": clientId}
    data = urllib.parse.urlencode(bodyDict).encode("utf-8")
    response = httpPost(TokenUrl, data, headers)
    if response is not None and response != "":
        jsonObject = json.loads(response)
        accessToken = jsonObject['access_token']
        # TODO: 将accessToken打印到控制台,您可以移除本句
        print(accessToken)
    return accessToken


def httpPost(url, params, headers):
    """Http post的工具方法."""
    global accessToken
    response, statusCode = doPost(url, params, headers)
    # 当状态码为401，表示AT已过期
    if statusCode == 401:
        # 刷新AT
        accessToken = None
        appAt = getAppAT()
        headers = buildAuthorization(appAt)
        # 再次请求
        response, statusCode = doPost(url, params, headers)
    elif statusCode != 200:
        print("request error: " + response)
        response = None
    return response


def doPost(url, params, headers):
    """执行post请求"""
    try:
        errorPro = BetterHTTPErrorProcessor()
        opener = urllib.request.build_opener(errorPro)
        req = urllib.request.Request(url=url, data=params, headers=headers, unverifiable=False, method="POST")
        response = opener.open(req, timeout=50)
        statusCode = response.getcode()
        return str(response.read(), encoding="utf8"), statusCode
    except urllib.error.URLError as e:
        print(e)


def buildAuthorization(appAt):
    """在请求头中构建Authorization"""
    oriString = "APPAT:%s" % appAt
    authorization = "Basic %s" % str(base64.b64encode(oriString.encode('utf-8')), 'utf-8')
    headers = {"Authorization": authorization, "Content-Type": "application/json; charset=UTF-8"}
    return headers


class BetterHTTPErrorProcessor(urllib.request.HTTPErrorProcessor):
    """重写HTTPErrorProcessor."""
    handler_order = 1000

    def http_response(self, request, response):
        code, msg, hdrs = response.code, response.msg, response.info()
        if not (200 <= code < 500):
            response = self.parent.error(
                'http', request, response, code, msg, hdrs)
        return response
    https_response = http_response

def get_withdrawal():
    """
    撤销订阅 (会取消订阅状态)
    功能介绍
    此接口用于撤销订阅，订阅型商品会立即取消，同时会立即发起退费。

    场景描述
    在收到用户申诉误购买该订阅型商品或不需要该订阅型商品的情况下，您可以调用华为应用内支付服务器提供的撤销订阅接口终止服务，购买的订阅型商品立即消失，同时这笔订阅费用会立即发起返还；一般，您或者华为在怀疑用户有欺诈行为时使用。
    :return:
        注意替换  使用线上回调的信息替换
        payload = {
        "purchaseToken": "00000196cda6de6e69d539c698bf0dc7c0dcbf1ad60f7563de53a9d162f6d2c2d92e965ae3eff6bbx434e.1.0829",
        "subscriptionId": "1747206987366.B5CE1032.0829"
    }

    """

    url = "https://subscr-drcn.iap.cloud.huawei.com.cn/sub/applications/v2/purchases/withdrawal"

    payload = {
        "purchaseToken": "000001975deecc5fafcd191d5eb32f86154ccb1e815e3dd861f3cb62276a84a95349ddcc2b619734x434e.1.4147",
        "subscriptionId": "1749627620443.078A2D59.4147"
    }
    headers = {
        "Content-Type": "application/json; charset=UTF-8",
        "Authorization": "Basic QVBQQVQ6RFFFQkFNbE83S3BjdmkveFdaM0t2blJiNWNPb2czVUxxRm5nOFJsSVFEaXRWazVrZXl2NStkYTl4NGJHL2dLRG9KU2RxeC9HbnBzeDJFWTBJK2RBdnAzelJzbmFEY1oyem84YmhBPT0=",
        "Accept": "application/json",
        "Content-Length": "171",
        "content-type": "application/json"
    }

    response = requests.request("POST", url, json=payload, headers=headers)

    return response.text


def get_returnFee():
    """
    返还订阅费用 (不取消订阅状态)
    功能介绍
    此接口用于退款给用户，不会取消订阅，在订阅到期之前一直有效。

    场景描述
    本接口仅进行最近一次收据的退费操作，不会对订阅产生额外影响，订阅可以继续正常使用，到期后也会进行自动续费。当用户意外购买订阅型商品申诉退款时，可以调用返还订阅费用接口退还用户费用，让用户在本周期免费试用后考虑是否留存订阅关系。若用户下周期不想继续使用该订阅，您可主动调用取消订阅接口进行取消处理，也可让用户自行在HMS Core（APK）的订阅管理页中取消订阅。
    :return:
    注意替换  使用线上回调的信息替换
        payload = {
        "purchaseToken": "00000196cda6de6e69d539c698bf0dc7c0dcbf1ad60f7563de53a9d162f6d2c2d92e965ae3eff6bbx434e.1.0829",
        "subscriptionId": "1747206987366.B5CE1032.0829"
    }
    """

    url = "https://subscr-drcn.iap.cloud.huawei.com.cn/sub/applications/v2/purchases/returnFee"

    payload = {
        "purchaseToken": "00000196cda6de6e69d539c698bf0dc7c0dcbf1ad60f7563de53a9d162f6d2c2d92e965ae3eff6bbx434e.1.0829",
        "subscriptionId": "1747206987366.B5CE1032.0829"
    }
    headers = {
        "Content-Type": "application/json; charset=UTF-8",
        "Authorization": "Basic QVBQQVQ6RFFFQkFNbE83S3BjdmkveFdaM0t2blJiNWNPb2czVUxxRm5nOFJsSVFEaXRWazVrZXl2NStkYTl4NGJHL2dLRG9KU2RxeC9HbnBzeDJFWTBJK2RBdnAzelJzbmFEY1oyem84YmhBPT0=",
        "Accept": "application/json",
        "Content-Length": "171",
        "content-type": "application/json"
    }

    response = requests.request("POST", url, json=payload, headers=headers)

    return response.text


"""
脚本执行步骤
1.获取华为应用的token信息非我们应用token  
    print(getAppAT())
    print(buildAuthorization(getAppAT()))

2.在开始执行撤销订阅或者返还订阅费用场景 
    print(get_withdrawal)
    print(get_returnFee)
"""

if __name__ == '__main__':
    # print(getAppAT())
    # print(buildAuthorization(getAppAT()))
    print(get_withdrawal())
    # print(get_returnFee)  一次只执行一个场景